package com.pbs.ui;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

import com.pbs.contact.ClientContact;
import com.pbs.contact.Contact;
import com.pbs.net.WSF;
import com.pbs.ui.dialog.Dialog;
import com.pbs.ui.dialog.Dialog.Type;
import com.pbs.utils.ContactProvider;
import com.pbs.utils.DateFormat;
import com.pbs.utils.MyXStream;

@SuppressWarnings("deprecation")
public class ContactsScreen extends Activity implements View.OnCreateContextMenuListener, OnItemClickListener {

	private int numberOfItemSelected = 0;
	private int item_position_long_clicked;
	private static ArrayList<ClientContact> contacts;
	// private Map<Character, LinkedList<ClientContact>> sections = new
	// HashMap<Character, LinkedList<ClientContact>>();
	private ListView lv;
	private static ArrayAdapter<ClientContact> aa;
	private static ContactProvider cp;
	private Handler myHandler = new Handler();

	/**
	 * Ham nay dat lai gia tri cho bien: numberOfItemSelected Bien nay nham muc
	 * dich dem so item da select de set label cho menu item Select All truong
	 * hop numberOfItemSelected = so luong hien co thi set label la "Select All"
	 * nguoc lai thi set la "Unselect All"
	 */
	private void countItemChecked() {
		numberOfItemSelected = 0;
		for (int i = 0; i < contacts.size(); i++) {
			if (contacts.get(i).isChecked()) {
				numberOfItemSelected++;
			}
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.contact_list);
		lv = (ListView) findViewById(R.id.List);
		try {
			if (contacts == null) {
				if (cp == null) {
					cp = new ContactProvider();
					cp.setCr(getContentResolver());
					cp.setCur(getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, "display_name ASC"));
				}
				contacts = cp.readBaseContactInfo();
			}
			countItemChecked();
			if (aa == null)
				aa = new ArrayAdapter<ClientContact>(this, R.layout.item_contact_info, contacts) {
					@Override
					public View getView(int position, View v, ViewGroup parent) {
						if (v == null) {
							LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
							v = vi.inflate(R.layout.item_contact_info, null);
						}
						ClientContact contact = contacts.get(position);
						if (contact != null) {
							TextView tvTopLeftInfo = (TextView) v.findViewById(R.id.tvTopLeftInfo);
							TextView tvTopRightInfo = (TextView) v.findViewById(R.id.tvTopRightInfo);
							TextView tvBottomRightInfo = (TextView) v.findViewById(R.id.tvBottomRightInfo);
							TextView tvBottomLeftInfo = (TextView) v.findViewById(R.id.tvBottomLeftInfo);

							ImageView iv = (ImageView) v.findViewById(R.id.ImageContact);
							iv.setImageBitmap(contact.getBitmap());
							CheckBox chkSelectContact = (CheckBox) v.findViewById(R.id.chkSelectContact);

							chkSelectContact.setChecked(contact.isChecked());

							HashMap<String, String> info = cp.getContactInfoToShow(contact);
							tvTopLeftInfo.setText(contact.getDisplayName());
							tvTopLeftInfo.setText(contact.getFirstName(info.get("DisplayName")));
							tvTopRightInfo.setText(contact.getLastName(info.get("DisplayName")));
							tvBottomRightInfo.setText(info.get("BottomRightInfo"));
							tvBottomLeftInfo.setText(info.get("BottomLeftInfo"));
						}
						return v;
					}
				};
			lv.setOnCreateContextMenuListener(this);
			lv.setOnItemClickListener(this);
			lv.setAdapter(aa);
		} catch (Exception e) {
			e.printStackTrace();
			Dialog.show(this, "Error", "Code Line 268, " + e.getMessage(), null, null, null, null, Dialog.Type.ERROR);
		}
		// new AlertNewContact().start();
	}

	private static int newContactCountOnStart;

	// class AlertNewContact extends Thread {
	// public void run() {
	// while (!isFinishing()) {
	// try {
	// Thread.sleep(3000);
	// final int count =
	// WSF.getNewContactCount(AccountManagerScreen.getUsername());
	// if (count > newContactCountOnStart) {
	// newContactCountOnStart = count;
	// myHandler.post(new Runnable() {
	// @Override
	// public void run() {
	// Dialog.show("New Contact", "Have " + count +
	// " friend sent contact for you", "View", "Cancel", new OnClickListener() {
	//
	// @Override
	// public void onClick(DialogInterface dialog, int which) {
	// Intent intent = new Intent(ContactsScreen.this,
	// SenderContactListActivity.class);
	// startActivity(intent);
	// }
	// }, new OnClickListener() {
	//
	// @Override
	// public void onClick(DialogInterface dialog, int which) {
	// dialog.dismiss();
	// }
	// });
	// }
	// });
	// }
	//
	// } catch (InterruptedException e) {
	// e.printStackTrace();
	// }
	// }
	// Log.i("Thread tracking", "Thread request new contact finished");
	// }
	// }

	public void onItemClick(AdapterView<?> arg0, View v, int pos, long arg3) {
		try {
			// id_forecast = Integer.parseInt(contacts.get(pos).getId());
			// maxID = getMaxID();
			Intent i = new Intent();
			i.setAction(Intent.ACTION_VIEW);
			i.setData(Uri.withAppendedPath(android.provider.Contacts.People.CONTENT_URI, "" + contacts.get(pos).getId()));
			startActivity(i);
		} catch (Exception e) {
			new AlertDialog.Builder(ContactsScreen.this).setMessage(e.getMessage()).show();
		}
	}

	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
		AdapterView.AdapterContextMenuInfo info;
		try {
			info = (AdapterView.AdapterContextMenuInfo) menuInfo;
		} catch (ClassCastException e) {
			return;
		}

		menu.setHeaderTitle(contacts.get(item_position_long_clicked = info.position).getDisplayName());
		new MenuInflater(getApplication()).inflate(R.menu.context_menu, menu);
	}

	public static Contact contactSelected;

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.select: {
			contacts.get(item_position_long_clicked).setChecked(!contacts.get(item_position_long_clicked).isChecked());
			numberOfItemSelected += contacts.get(item_position_long_clicked).isChecked() ? 1 : -1;
			aa.notifyDataSetChanged();
			break;
		}
		case R.id.delete: {
			Dialog.show(this, "Confirm delete", "Are you sure you want to delete?", "Yes", "No", new OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					if (cp.deleteContactWithID(contacts.get(item_position_long_clicked).getId()) == 0) {
						if (cp.deleteContactWithName(contacts.get(item_position_long_clicked).getDisplayName()) == 0) {
							Toast.makeText(ContactsScreen.this, "Sorry!", Toast.LENGTH_SHORT);
						} else {
							contacts.remove(item_position_long_clicked);
							numberOfItemSelected--;
							aa.notifyDataSetChanged();
						}
					} else {
						contacts.remove(item_position_long_clicked);
						numberOfItemSelected--;
						aa.notifyDataSetChanged();
					}
				}
			}, new OnClickListener() {

				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			}, Type.CONFIRM);
			break;
		}
		case R.id.edit: {
			// id_forecast =
			// Integer.parseInt(contacts.get(item_position_long_clicked).getId());
			// maxID = getMaxID();
			Intent i = new Intent();
			i.setAction(Intent.ACTION_EDIT);
			i.setData(Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, "" + contacts.get(item_position_long_clicked).getId()));
			startActivity(i);
			break;
		}
		}
		return true;
	}

	/**
	 * When have just add contact or update contact and revert this screen then
	 * list contact cannot auto refresh even you read again all of contact and
	 * use method notifyDataSetChanged(). Unless you recall method onCreate So,
	 * this problem need optimization. Solution for this problem is se...
	 */

	// private int getMaxID() {
	// int max = 0;
	// for (int i = 0; i < contacts.size(); i++) {
	// int id = Integer.parseInt(contacts.get(i).getId());
	// if (max < id) {
	// max = id;
	// }
	// }
	// return max;
	// }

	// int id_forecast = -1;
	// int maxID = 0;

	@Override
	protected void onRestart() {
		// Need get contact's id have just update or add
		onCreate(getIntent().getExtras());

		// instance of add new contact
		// Log.i("IDF", "" + id_forecast);
		// Log.i("ID MAX", "" + maxID);
		//
		// if (id_forecast == maxID + 1) {
		// ClientContact cc = cp.readContact("" + id_forecast);
		// for (int i = 0; i < contacts.size(); i++) {
		// if (contacts.get(i).getDisplayName().charAt(0) ==
		// cc.getDisplayName().charAt(0)) {
		// contacts.add(i, cc);
		// }
		// }
		// }
		// // Instance of update contact
		// if (id_forecast <= maxID && id_forecast >= 0) {
		// ClientContact contact = cp.readContact("" + id_forecast);
		// for (int i = 0; i < contacts.size(); i++) {
		// ClientContact contact1 = contacts.get(i);
		// if (contact1.getId().equals("" + id_forecast)) {
		// contacts.remove(i);
		// contacts.add(i, contact);
		// break;
		// }
		// }
		// }
		// Log.i("contacts size", "" + contacts.size());
		// aa.notifyDataSetChanged();
		super.onRestart();
	}

	public void contactCheckButtonClick(View v) {
		CheckBox chk = (CheckBox) v;
		int pos = lv.getPositionForView(v);
		Contact myContact = aa.getItem(pos);
		myContact.setChecked(chk.isChecked());
		numberOfItemSelected += chk.isChecked() ? 1 : -1;
	}

	public boolean onCreateOptionsMenu(Menu menu) {
		new MenuInflater(getApplication()).inflate(R.menu.options_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onMenuOpened(int featureId, Menu menu) {
		if (numberOfItemSelected == contacts.size()) {
			menu.findItem(R.id.select_all).setTitle(R.string.option_menu_item_UnselectAll);
		} else {
			menu.findItem(R.id.select_all).setTitle(R.string.option_menu_item_SelectAll);
		}
		return super.onMenuOpened(featureId, menu);
	}

	public static String getContactsName() {
		return contacts_name;
	};

	public static String getContactsId() {
		return contacts_id;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		// Options menu
		case R.id.new_contact: {
			Log.i("contacts size", "" + contacts.size());
			// maxID = getMaxID();
			// id_forecast = maxID + 1;
			Intent i = new Intent();
			i.setAction(Intent.ACTION_INSERT);
			i.setData(ContactsContract.Contacts.CONTENT_URI);
			startActivity(i);
			break;
		}
		case R.id.delete: {
			if (contacts.isEmpty()) {
				Toast.makeText(this, R.string.msg_EmptyListContact, Toast.LENGTH_LONG);
			} else {
				boolean hasCheck = false;
				for (Contact contact : contacts) {
					if (contact.isChecked()) {
						hasCheck = true;
						break;
					}
				}
				if (hasCheck) {
					// get positions checked
					Dialog.show(this, "Confirm Delete", "Are you sure you want to delete?", "Yes", "No", new OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							final ProgressDialog pd = Dialog.showProgressDialog(ContactsScreen.this, "Deleting...", false);
							new Thread() {
								public void run() {
									int count = 0;
									for (int i = 0; i < contacts.size(); i++) {
										Contact myContact = contacts.get(i);
										if (myContact.isChecked()) {
											if (count < (count += cp.deleteContactWithID(myContact.getId()))) {
												contacts.remove(myContact);
												numberOfItemSelected--;
												i--;
											} else {
												if (count < (count += cp.deleteContactWithName(myContact.getDisplayName()))) {
													contacts.remove(myContact);
													numberOfItemSelected--;
													i--;
												}
											}
											myHandler.post(new Thread() {
												public void run() {
													pd.setMessage("Remaining " + numberOfItemSelected + " contact(s)");
												}
											});
										}
									}

									myHandler.post(new Thread() {
										public void run() {
											if (contacts.isEmpty()) {
												((TextView) findViewById(R.id.tvMessageEmptyList)).setText(R.string.msg_EmptyListContact);
											} else {
												((TextView) findViewById(R.id.tvMessageEmptyList)).setText("");
											}
											aa.notifyDataSetChanged();
											pd.dismiss();
										}
									});
								}
							}.start();

						}
					}, new OnClickListener() {

						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();
						}
					}, Type.CONFIRM);
				} else {
					Toast.makeText(this, R.string.msg_WhenDontSelectContact, Toast.LENGTH_LONG);
				}
			}

			break;
		}

		case R.id.backup: {
			if (contacts.isEmpty()) {
				Toast.makeText(this, R.string.msg_EmptyListContact, Toast.LENGTH_LONG);
			} else {
				showBackupDialog();
			}
			break;
		}
		case R.id.restore: {
			startActivity(new Intent(this, RestoreContactActivity.class));
			break;
		}
		case R.id.friend_manager: {
			startActivity(new Intent(this, FriendListActivity.class));
			break;
		}
		case R.id.import_sim: {

			break;
		}

		case R.id.export_sd_card: {
			if (contacts.isEmpty()) {
				Toast.makeText(this, R.string.msg_EmptyListContact, Toast.LENGTH_LONG);
			} else {
				if (numberOfItemSelected == 0) {
					Toast.makeText(this, R.string.msg_WhenDontSelectContact, Toast.LENGTH_LONG);
				} else {
					File root = Environment.getExternalStorageDirectory();
					if (root.canWrite()) {
						final File gpxfile = new File(root, "export.xml");
						if (gpxfile.exists()) {
							Dialog.show(this, "File existed", "Would you like to replace the existing file?", "Yes", "No", new OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) {
									ArrayList<Contact> contactsToShare = new ArrayList<Contact>();
									for (ClientContact contact : contacts) {
										if (contact.isChecked()) {
											contactsToShare.add(cp.readContact(contact.getId()));
										}
									}
									exportContactToSDCard(contactsToShare, gpxfile);
								}
							}, new OnClickListener() {

								public void onClick(DialogInterface dialog, int which) {
									dialog.dismiss();
								}
							}, Type.CONFIRM);
						} else {
							ArrayList<Contact> contactsToShare = new ArrayList<Contact>();
							for (ClientContact contact : contacts) {
								if (contact.isChecked()) {
									contactsToShare.add(cp.readContact(contact.getId()));
								}
							}
							exportContactToSDCard(contactsToShare, gpxfile);
						}
					} else {
						Toast.makeText(this, "Cannot write on SDCard", Toast.LENGTH_LONG);
					}
				}
			}
			break;
		}

		case R.id.import_sd_card: {
			File root = Environment.getExternalStorageDirectory();
			if (root.canRead()) {
				if (new File(root, "export.xml").exists()) {
					startActivity(new Intent(this, ImportContactFromSDCardActivity.class));
				} else {
					Toast.makeText(this, "Cannot found file export.xml on SDCard", Toast.LENGTH_LONG);
				}
			} else {
				Toast.makeText(this, "Access denied!", Toast.LENGTH_LONG);
			}

			break;
		}

		case R.id.send: {
			try {
				if (contacts.isEmpty()) {
					Toast.makeText(this, R.string.msg_EmptyListContact, Toast.LENGTH_LONG);
				} else {
					if (numberOfItemSelected == 0) {
						Toast.makeText(this, R.string.msg_WhenDontSelectContact, Toast.LENGTH_LONG);
					} else {
						String[] ids = new String[numberOfItemSelected];
						int i = 0;
						for (Contact contact : contacts) {
							if (contact.isChecked()) {
								ids[i++] = contact.getId();
							}
						}
						Intent intent = new Intent(this, SendContactActivity.class);
						intent.putExtra("ArrayId", ids);
						contactSelected = null;
						startActivity(intent);
					}
				}
			} catch (Exception e) {
				new AlertDialog.Builder(ContactsScreen.this).setMessage("Error backupcontact " + e.getMessage()).show();
			}

			break;
		}

		case R.id.receive: {
			startActivity(new Intent(this, SenderContactListActivity.class));
			break;
		}
		case R.id.search: {
			onSearchRequested();
			break;
		}
		case R.id.select_all: {
			if (numberOfItemSelected == contacts.size()) {
				// Unselect all
				for (Contact contact : contacts) {
					contact.setChecked(false);
				}
				numberOfItemSelected = 0;
			} else {
				// select all
				for (Contact contact : contacts) {
					contact.setChecked(true);
				}
				numberOfItemSelected = contacts.size();
			}
			aa.notifyDataSetChanged();
			break;
		}
		case R.id.change_password: {
			changePassword();
			break;
		}
		}
		return super.onOptionsItemSelected(item);
	}

	private void exportContactToSDCard(final ArrayList<Contact> contactsToShare, final File gpxfile) {
		try {
			FileWriter gpxwriter = new FileWriter(gpxfile);
			BufferedWriter out = new BufferedWriter(gpxwriter);
			String xml_content = MyXStream.toXML(contactsToShare);
			out.write(xml_content);
			out.close();
			new AlertDialog.Builder(ContactsScreen.this).setMessage("The contacts shared to file export.xml").setTitle("Export success!").setPositiveButton("OK", new OnClickListener() {

				public void onClick(DialogInterface dialog, int which) {
					for (Contact contact : contacts) {
						contact.setChecked(false);
					}
					aa.notifyDataSetChanged();
				}
			}).show();
		} catch (IOException e) {
			Dialog.show(this, "IOException", "error while attemping to write file on SDCard", null, null, null, null, Type.MESSAGE);
		}
	}

	private void changePassword() {
		LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View content = vi.inflate(R.layout.change_password, null);

		final EditText inputBoxOldPassword = (EditText) content.findViewById(R.id.txtOldPassword);
		final EditText inputBoxNewPassword = (EditText) content.findViewById(R.id.txtNewPassword);
		final EditText inputBoxConfirm = (EditText) content.findViewById(R.id.txtConfirmPassword);

		new AlertDialog.Builder(this).setView(content).setTitle("New Password").setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				String old_password = inputBoxOldPassword.getText().toString();
				final String new_password = inputBoxNewPassword.getText().toString();
				String confirm_password = inputBoxConfirm.getText().toString();
				if (new_password.equals("") || confirm_password.equals("")) {
					Dialog.show(ContactsScreen.this, null, "password isn't empty", null, null, null, null, Type.MESSAGE);
				} else {
					if (!AccountManagerScreen.getPassword().equals(old_password))
						Toast.makeText(ContactsScreen.this, "Old password incorrect", Toast.LENGTH_LONG);
					else {
						if (!new_password.equals(confirm_password))
							Toast.makeText(ContactsScreen.this, "Password confirm incorrect", Toast.LENGTH_LONG);
						else {
							final ProgressDialog pd = Dialog.showProgressDialog(ContactsScreen.this, "Please waiting...", false);
							new Thread(new Runnable() {

								@Override
								public void run() {
									try {
										if (WSF.changePassword(AccountManagerScreen.getUsername(), new_password)) {
											myHandler.post(new Runnable() {
												public void run() {
													Toast.makeText(ContactsScreen.this, "Your password changed", Toast.LENGTH_LONG);
												}
											});
										} else {
											myHandler.post(new Runnable() {
												public void run() {
													Toast.makeText(ContactsScreen.this, "Have an unknow error when attempting to change password!", Toast.LENGTH_LONG);
												}
											});
										}
										myHandler.post(new Runnable() {
											public void run() {
												pd.dismiss();
											}
										});
									} catch (final Exception e) {
										myHandler.post(new Runnable() {
											public void run() {
												pd.dismiss();
												Dialog.show(ContactsScreen.this, "Error!", "System:\n" + e.getMessage(), null, null, null, null, Type.ERROR);
											}
										});
									}
								}
							}).start();
						}

					}
				}
			}
		}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				d.dismiss();
			}
		}).create().show();
	}

	public void showBackupDialog() {
		final LinearLayout ll = new LinearLayout(this);
		final EditText inputBoxNotes = new EditText(this, null);

		ll.setOrientation(LinearLayout.VERTICAL);
		ll.setPadding(5, 5, 5, 5);
		ll.addView(inputBoxNotes, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
		inputBoxNotes.setHint("Notes");
		new AlertDialog.Builder(this).setView(ll).setIcon(R.drawable.backup_icon).setTitle("Backup Contact").setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				final ProgressDialog pd = Dialog.showProgressDialog(ContactsScreen.this, null, "Please waiting", false);
				new Thread() {
					public void run() {
						String notes = inputBoxNotes.getText().toString();
						try {
							if (WSF.backupContactList(cp.readFullContactInfo(), AccountManagerScreen.getUserID(), notes, com.pbs.utils.Date.getDate(DateFormat.DDMMYYYY, "-"),
									com.pbs.utils.Date.getTime())) {
								myHandler.post(new Runnable() {
									public void run() {
										Toast.makeText(ContactsScreen.this, "Backup completed", Toast.LENGTH_LONG);
									}
								});
							} else {
								myHandler.post(new Runnable() {
									public void run() {
										Toast.makeText(ContactsScreen.this, "Backup error!", Toast.LENGTH_LONG);
									}
								});
							}
						} catch (final Exception e) {
							myHandler.post(new Runnable() {
								public void run() {
									Dialog.show(ContactsScreen.this, "Error!", "Please check again connection.\n" + e.getMessage(), null, null, null, null, Type.ERROR);
								}
							});
						}
						pd.dismiss();
					}
				}.start();
			}
		}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				d.dismiss();
			}
		}).create().show();
	}

	private static String contacts_name = "";
	private static String contacts_id = "";
}
